#include "Frame.h"
#include <algorithm>
#include "../../tools/Log.h"
#include "../../draw/DrawSystem.h"
#include "Text.h"
#include "Picture.h"
#include "Button.h"

using namespace std;

Frame::Frame()
: objs()
, pos()
, dimensions()
, horizalign(HORIZ_MIDDLE)
, vertalign(VERT_MIDDLE)
{}

Frame::~Frame() {
	//Clean out all objects
	for(ObjectList::iterator itr = objs.begin(); itr != objs.end(); itr++)
		delete *itr;
	objs.clear();
}

void Frame::parseChild(ticpp::Node* node, int z, Frame* f) {
	using namespace ticpp;
	std::string val;
	Node *child = NULL;
	while( (child = node->IterateChildren( child )) != NULL) {
		child->GetValue(&val);
		
// See what kind of object we're asked to load
		if(val == "Text") {
			TextObject* txt = new TextObject();
			txt->loadFromXML(child, z-1, f);		//Load the next child as text at the next closest draw depth
			f->objs.insert(txt);
		} else if(val == "Picture") {
			Picture* pic = new Picture();
			pic->loadFromXML(child, z-1, f);		//Load the next child as text at the next closest draw depth
			f->objs.insert(pic);
		} else if(val == "Button") {
			Button* button = new Button();
			button->loadFromXML(child, z-1, f);	//Load the next child as text at the next closest draw depth
			f->objs.insert(button);
		}
		else
			throw Exception("Frame child was not a valid type");
	}
}

bool Frame::leftClick(float x, float y) {
	vector<Object*> obs = select(x,y);		//Get all objects that pass the hit test
	if(obs.empty())
		return false;
// Go over all objects, if they have an associated key, call the left click
	for(vector<Object*>::iterator itr = obs.begin(); itr != obs.end(); itr++)
		if((*itr)->myKey != KEY_VOID)
			(*itr)->onLeftClick();
	return true;
}

void Frame::rollOver(float x, float y) {
	vector<Object*> obs = select(x,y);
	for(vector<Object*>::iterator itr = obs.begin(); itr != obs.end(); itr++)
		(*itr)->onRollOver();
}

bool Frame::keyPress(KEY_TYPE b) {
	Object* obj = select(b);
	if(obj != NULL) {
		obj->onKeyPress();
		return true;	
	}
	return false;
}

std::vector<Object*> Frame::select(float x, float y) {
	ObjectClickHit och(x,y);
	vector<Object*> obs;
// Loop over all objects and perform the hit test
	for(ObjectList::iterator it = objs.begin(); it != objs.end(); it++)
		if(och(*it))
			obs.push_back(*it);

	return obs;
}

Object* Frame::select(KEY_TYPE k) {
// Use STL to find the first object that maps to our key
	ObjectList::iterator it = std::find_if(objs.begin(), objs.end(), ObjectKeyEqual(k));
	if(it == objs.end())
		return NULL;
	return *it;
}

void Frame::enable() {
// Enable everyone
	for(ObjectList::iterator itr = objs.begin(); itr != objs.end(); itr++)
		(*itr)->enable();
}

void Frame::disable() {
// Disable everyone
	for(ObjectList::iterator itr = objs.begin(); itr != objs.end(); itr++)
		(*itr)->disable();
}

void Frame::onWindowResize(float width, float height) {
	switch(horizalign) {
	case LEFT:
		pos.x = 0;
		break;
	case RIGHT:
		pos.x = width - dimensions.x;
		break;
	case HORIZ_MIDDLE:
		pos.x = (width - dimensions.x) / 2.0;
		break;
	case ABSOLUTE:
	default:
		break;
	}
	switch(vertalign) {
	case TOP:
		pos.y = height - dimensions.y;
		break;
	case BOTTOM:
		pos.y = 0;
		break;
	case VERT_MIDDLE:
		pos.y = (height - dimensions.y) / 2.0;
		break;
	case ABSOLUTE:
	default:
		break;
	}
	
	//Tell all children to realign in accordance to this frame
	for(ObjectList::iterator itr = objs.begin(); itr != objs.end(); itr++)
		(*itr)->onRealign(pos.x, pos.x+dimensions.x, pos.y, pos.y+dimensions.y);
}

void Frame::loadFromXML(ticpp::Node* node) {
	using namespace ticpp;
	string val;
	
	Element* elem = node->ToElement();
	elem->GetAttribute("x", &pos.x, false);
	elem->GetAttribute("y", &pos.y, false);
	elem->GetAttribute("width", &dimensions.x, false);
	elem->GetAttribute("height", &dimensions.y, false);
	elem->GetAttribute("horizAlignment", &val, false);
	getAlignment(horizalign, val, true);
	elem->GetAttribute("vertAlignment", &val, false);
	getAlignment(vertalign, val, true);
	
	Frame::parseChild(node, DrawSystem::BACKGROUND, this);	
}

